package us.norepeter.processing.textmatcher;

import java.util.Enumeration;

public abstract class AbstractTransformer 
	extends TextProcessingChainLink implements Transformer {

	String defaultProperty;
	String extractIntoProperty;
	String transformationName;

	public AbstractTransformer(String name) {
		transformationName = name;
		defaultProperty = null;
	}

	/*
	 * Set a default property to be transformed
	 */
	public AbstractTransformer(String name, String defaultProperty) {
		this.defaultProperty = defaultProperty;
		transformationName = name;
	}

	/*
	 * Set a default property to affect, and a property to store the change in
	 */
	public AbstractTransformer(String name, String defaultProperty, String extractInto) {
		this.defaultProperty = defaultProperty;
		transformationName = name;
		extractIntoProperty = extractInto;
	}

	public void transformAll(Entity s) {
		Enumeration<?> e = s.propertyNames();
		while (e.hasMoreElements()) {
			String propName = (String) e.nextElement();
			transform(s, propName);
		}
	}

	public String transform(String s) {
		return s;
	}

	public SplitTransformation splitTransformation(String s) {
		return new SplitTransformation("", "");
	}

	public boolean transform(Entity s, String property) {
		String currentValue = getProp(s, property);
		String newValue = transform(currentValue);
		s.setProperty(property, newValue);
		return (!(newValue.length() > "".length() && newValue
				.equals(currentValue)));
	}

	public boolean extractTransformation(Entity s, String from, String to) {
		String currentValue = getProp(s, from);
		SplitTransformation nextVals = splitTransformation(currentValue);
		String replacement = nextVals.getBefore();
		String extraction = nextVals.getAfter();
		s.setProperty(from, replacement);
		s.setProperty(to, extraction);
		return extraction.length() > "".length()
				&& !(replacement.equals(currentValue));
	}

	private String getProp(Entity e, String prop) {
		String currentValue = e.getProperty(prop);
		return (currentValue == null) ? "" : currentValue;
	}

	/*
	 * Apply the transformation to this transformation's default property. If
	 * there is no default property, applies the transformation to all the
	 * properties in this entity.
	 */
	@Override
	public boolean transform(Entity s) {
		if (defaultProperty == null) {
			transformAll(s);
			return true;
		}
		if (s.containsKey(defaultProperty)) {
			if (extractIntoProperty != null) {
				return extractTransformation(s, defaultProperty,
						extractIntoProperty);
			}
			return transform(s, defaultProperty);
		}
		return false;
	}

	/**
	 * Class used to encapsulate details of a split transformation
	 * 
	 * @author ##author##
	 */
	public class SplitTransformation {

		private String before;
		private String after;

		public SplitTransformation(String before, String after) {
			this.before = before;
			this.after = after;
		}

		public String getBefore() {
			return before;
		}

		public String getAfter() {
			return after;
		}
	}
}
